package com.atguigu.tingshu.order.strategy.Impl;

import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.order.OrderDerate;
import com.atguigu.tingshu.model.order.OrderDetail;
import com.atguigu.tingshu.model.order.OrderInfo;
import com.atguigu.tingshu.order.service.OrderDerateService;
import com.atguigu.tingshu.order.service.OrderDetailService;
import com.atguigu.tingshu.order.service.OrderInfoService;
import com.atguigu.tingshu.order.strategy.SaveOrderStrategy;
import com.atguigu.tingshu.vo.order.OrderDerateVo;
import com.atguigu.tingshu.vo.order.OrderDetailVo;
import com.atguigu.tingshu.vo.order.OrderInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WeiXinSaveOrderStrategy implements SaveOrderStrategy {

    @Autowired
    private OrderInfoService orderInfoService ;

    @Autowired
    private OrderDetailService orderDetailService ;

    @Autowired
    private OrderDerateService orderDerateService ;

    @Autowired
    private RedissonClient redissonClient ;

    @Override
    @Transactional      // 把多个操作纳入到一个事务中，这种方式会不会有问题？事务不会失效
    public OrderInfoVo saveOrder(OrderInfoVo orderInfoVo) {

        /**
         * 保存前端提交过来的表单数据到指定的数据库中：
         * 1、保存订单的基本数据 order_info
         * 2、保存订单的明细数据 order_detail
         * 3、保存订单减免明细数据  order_derate
         */
        // 订单一个保存订单相关数据方法
        // WeiXinSaveOrderStrategy saveOrderStrategy = (WeiXinSaveOrderStrategy) AopContext.currentProxy();
        this.saveOrderInfoAndDrateInfoAndDetailInfo(orderInfoVo,orderInfoService,orderDerateService,orderDetailService) ;

        // 发布延迟任务
        sendDelayTask(orderInfoVo.getTradeNo()) ;

        return orderInfoVo;
    }

    // 发布一个延迟任务
    private void sendDelayTask(String tradeNo) {

        // 获取阻塞队列对象
        RBlockingDeque<String> blockingDeque = redissonClient.getBlockingDeque(RedisConstant.DELAY_QUEUE_ORDER_CANCEL);
        RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);         // 获取延迟队列
        delayedQueue.offer(tradeNo , RedisConstant.DELAY_TIME , TimeUnit.SECONDS);

    }

    /*
       spring事务的底层原理, spring的事务控制本质上是通过动态代理进行实现，因此要进行事务控制必须通过代理对应调用对应的方法。
     */
    // @Transactional      // 把多个操作纳入到一个事务中，这种方式会不会有问题？ 会导致事务失效，自调用问题


    @Override
    public String getPayWay() {
        return SystemConstant.ORDER_PAY_WAY_WEIXIN;     // 1101
    }

    @Override
    public void saveOrderProcess(String orderNo) {

    }

}
